<script setup lang="ts">
import * as echarts from 'echarts'
import type { EChartsOption } from 'echarts'

const props = withDefaults(defineProps<{
  option?: EChartsOption | null
  loading?: boolean
  height?: string
}>(), {
  loading: false,
  height: '320px',
})

const chartEl = ref<HTMLDivElement | null>(null)
let chart: echarts.ECharts | null = null
let ro: ResizeObserver | null = null
let initTimer: number | null = null
let attempts = 0
const maxAttempts = 30
const lastOption = ref<EChartsOption | null>(null)

function ensureChartInit() {
  if (chart || !chartEl.value)
    return
  const el = chartEl.value
  const width = el.clientWidth
  const height = el.clientHeight
  if (width > 0 && height > 0) {
    chart = echarts.init(el)
    if (lastOption.value)
      chart.setOption(lastOption.value, true)
    chart.resize()
    return
  }
  // 继续重试，等待父容器尺寸就绪
  if (attempts < maxAttempts) {
    attempts += 1
    initTimer = window.setTimeout(ensureChartInit, 100)
  }
}

function render(opt?: EChartsOption | null) {
  lastOption.value = opt ?? null
  ensureChartInit()
  if (chart && opt)
    chart.setOption(opt, true)
  chart?.resize()
}

function handleResize() {
  ensureChartInit()
  chart?.resize()
}

watch(() => props.option, (opt) => {
  render(opt || undefined)
}, { deep: true })

onMounted(() => {
  attempts = 0
  ensureChartInit()
  // 监听容器尺寸变化（包括父级布局变化）
  if (chartEl.value && typeof ResizeObserver !== 'undefined') {
    ro = new ResizeObserver(() => {
      handleResize()
    })
    ro.observe(chartEl.value)
  }
  window.addEventListener('resize', handleResize)
})

onUnmounted(() => {
  window.removeEventListener('resize', handleResize)
  ro?.disconnect()
  ro = null
  if (initTimer) {
    clearTimeout(initTimer)
    initTimer = null
  }
  chart?.dispose()
  chart = null
})
</script>

<template>
  <a-spin :spinning="props.loading" :style="{ display: 'block', width: '100%', height: props.height === 'auto' ? '100%' : props.height, minHeight: props.height === 'auto' ? '240px' : undefined }">
    <div :style="{ width: '100%', height: '100%', minHeight: props.height === 'auto' ? '240px' : undefined }" ref="chartEl" />
  </a-spin>
</template>

<style scoped>
/* 容器占位并铺满父容器，避免初始化时百分比高度失效 */
:host {
  display: block;
  width: 100%;
  height: 100%;
}
</style>